#include<iostream>
#include<cstdio>
#include<unistd.h>
#include<signal.h>
#include<cassert>
#include<sys/types.h>
#include<sys/wait.h>

using namespace std;

// void clean(int signo)
// {
//     if(signo == SIGCHLD)
//     {
//         /*在同一时刻多个子进程退出,会同时向父进程发送SIGCHLD信号,
//         但pending位图只会记录一次,即只清理了一个子进程的资源,
//         所以使用while循环*/
//         while(true) 
//         {
//             /*若为阻塞等待,只有部分子进程退出,由于while循环,
//             会再次调用waitpid,就会一直在这阻塞,所有使用非阻塞轮询等待*/
//             pid_t rid = waitpid(-1, nullptr, WNOHANG);
//             if(rid > 0)
//                 cout << "child wait success!" << endl;
//             else break;
//         }
//     }
// }

int main()
{
    //子进程在终止时自动清理掉，不会产生僵尸，也不会通知父进程
    signal(SIGCHLD, SIG_IGN); 

    for(int i = 0; i < 100; i++) //父进程创建100个子进程
    {
        pid_t id = fork();
        if(id == 0)
        {
            cout << "I am child process, pid: " << getpid() << endl;
            exit(0); //100个子进程全部退出
        }

        sleep(1);
    }

    return 0;
}

//  void PrintSig(sigset_t pending) 
//  {
//     cout << "pending bitmap: ";

//     for(int i = 31; i > 0; i--)     
//     {
//         if(sigismember(&pending, i))
//             cout << "1";
//         else cout << "0";
//     }
//     cout << endl;
//     sleep(1);
//  }

// void handler(int signo) 
// {
//     cout << "get signo: " << signo << endl;
//     sigset_t pending;
//     sigemptyset(&pending);
//     while(true)
//     {

//         int n3 = sigpending(&pending);
//         assert(n3 == 0);

//         PrintSig(pending);  
//     }
// }

// int main()
// {
//     struct sigaction act, oact;
//     act.sa_handler = handler;
//     act.sa_flags = 0;
//     sigemptyset(&act.sa_mask);
//     sigaddset(&act.sa_mask, 3);
//     sigaddset(&act.sa_mask, 4);
//     sigaddset(&act.sa_mask, 5);
    
//     int n = sigaction(2, &act, &oact);
//     assert(n == 0);

//     cout << "I am a process! pid: " << getpid() << endl;
//     while(true)
//         sleep(1);

//     return 0;
// }

// int main()
// {
//     sigset_t set, oldset;
//     sigemptyset(&set);
//     sigemptyset(&oldset);
//     cout << "begin block all signo! pid: " << getpid() << endl;
//     for(int i = 31; i > 0; i--) //将1~31号阻塞
//     {
//         sigaddset(&set, i);
//         int n1 = sigprocmask(SIG_SETMASK, &set, &oldset);
//         assert(n1 == 0);
//     }

//     while(true)
//     {
//         sigset_t pending;
//         sigemptyset(&pending);
//         int n2 = sigpending(&pending); //获取pending位图
//         assert(n2 == 0);

//         PrintSig(pending); //打印pending位图
//     }

//     return 0; 
// }

// int main()
// {
//     signal(2, handle);  //设置2号信号捕捉的方法

//     //1.阻塞2号信号
//     sigset_t set, oldset;
//     sigemptyset(&set);
//     sigaddset(&set, 2);
//     sigemptyset(&oldset);
//     int n1 = sigprocmask(SIG_SETMASK, &set, &oldset);
//     assert(n1 == 0);
//     cout << "block 2 signo success! pid: " << getpid() << endl;
//     sleep(1);

//     int cnt = 0;
//     while(true)
//     {
//         //2.获取penging位图
//         sigset_t pending;
//         sigemptyset(&pending);
//         int n2 = sigpending(&pending);
//         assert(n2 == 0);

//         //3.打印pending位图
//         PrintSig(pending);
//         cnt++;

//         //4.解除对2号信号的阻塞
//         if(cnt == 8) 
//         {
//             cout << "release 2 signo block!" << endl;
//             n2 = sigprocmask(SIG_UNBLOCK, &set, &oldset); //解除完后,立即递达
//             assert(n2 == 0);
//         }

//     }
    
//     return 0;
// }